(function(){
	var plugor = window.plugor = {};
	plugor.extend = function() {
		// copy reference to target object
		var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
	
		// Handle a deep copy situation
		if ( target.constructor == Boolean ) {
			deep = target;
			target = arguments[1] || {};
			// skip the boolean and the target
			i = 2;
		}
	
		// Handle case when target is a string or something (possible in deep copy)
		if ( typeof target != "object" && typeof target != "function" )
			target = {};
	
		// extend plugor itself if only one argument is passed
		if ( length == i ) {
			target = this;
			--i;
		}
	
		for ( ; i < length; i++ )
			// Only deal with non-null/undefined values
			if ( (options = arguments[ i ]) != null )
				// Extend the base object
				for ( var name in options ) {
					var src = target[ name ], copy = options[ name ];
	
					// Prevent never-ending loop
					if ( target === copy )
						continue;
	
					// Recurse if we're merging object values
					if ( deep && copy && typeof copy == "object" && !copy.nodeType )
						target[ name ] = plugor.extend( deep, 
							// Never move original objects, clone them
							src || ( copy.length != null ? [ ] : { } )
						, copy );
	
					// Don't bring in undefined values
					else if ( copy !== undefined )
						target[ name ] = copy;
	
				}
	
		// Return the modified object
		return target;
	};
	
	/*@Annotations
		{parent:'',name:'工具篇',title:'工具篇',describe:''}
	*/
	plugor.extend({
		fn:{},
		/*@Annotations
			{parent:'工具篇',name:'getType(o)',title:'获取对象类型',describe:'返回对象类型\n调用方法:plugor.getType(o);'}
		*/
		getType : function(x) {
			// If x is null, return "null"
			// x是null，返回“null”
			if (x == null)
				return "null";
	
			// Next try the typeof operator
			// 先用基础的typeof判定
			var t = typeof x;
			// If the result is not vague, return it
			if (t != "object")
				return t;
	
			// Otherwise, x is an object. Use the default toString( ) method to
			// get the class value of the object.
			// 对于object对象，typeof无能为力，我们来找找对象的class值
			var c = Object.prototype.toString.apply(x); // Returns "[object class]"
			c = c.substring(8, c.length - 1); // Strip off "[object" and "]"
	
			// If the class is not a vague one, return it.
			// 如果有具体的class值，而不是单纯的“object"
			if (c != "Object")
				return c;
	
			// If we get here, c is "Object". Check to see if
			// the value x is really just a generic object.
			// 函数运行到这里，那么该对象就是一个Object
			if (x.constructor == Object)
				return c; // Okay the type really is "Object"
			// For user-defined classes, look for a string-valued property named
			// classname, that is inherited from the object's prototype
			// 也有可能是自定义类，我们找一下它的构造函数中是否定义了classname这个属性
			if ("classname" in x.constructor.prototype && // inherits classname
					typeof x.constructor.prototype.classname == "string") // its a
																			// string
				return x.constructor.prototype.classname;
	
			// If we really can't figure it out, say so.
			return "<unknown type>";
		},
		bind:function(elem, type, handler, bubble) {
			var callbackHandler = function(e) {
				var ev = window.event || e;
				var elem = ev.srcElement || ev.target;
				if(bubble) {
					if (window.event) {
						ev.cancelBubble = true;
					} else {
						ev.stopPropagation();
					}
				}
				return handler(elem, ev);
			};
			if(elem.addEventListener) {
				elem.addEventListener(type, callbackHandler, false);
			} else {
				elem.attachEvent('on' + type, callbackHandler);
			}
		},
		unbind:function(elem, type, handler) {
			elem.removeEventListener ? elem.removeEventListener(type, handler, false)
					: elem.detachEvent('on' + type, elem[type + handler]);
		},
		createElement:function(name,attr){
			var o = document.createElement(name);
			for(var key in attr){
				o.setAttribute(key, attr[key]);
			}
			return o;
		},
		/*
		 * 
		 */
		getParameter:function (key,uri){
			return (new RegExp("([^(&|\?)]*)" + key + "=([^(&|#)]*)").test(uri+"#")) ? RegExp.$2 : null;
		},
		len:function(str){
			return str?str.replace(/[^\x00-\xff]/g,"xx").length:0;
		},
		/*@Annotations
			{parent:'工具篇',name:'startsWith(str,prefix,bool)',title:'',
				describe:'判断字符串是否以XX开头\n
					调用方法:plugor.startsWith(str, prefix,bool);
					@return boolean
					@param
						str:被判断字符串;
						prefix:判断开头字符串;
						bool:是否区分大小写,为true则不区分大小写,false则区分大小写;
					@eg
						var str = "abcdef";
						plugor.startsWith(str,'ab');//return true;
						plugor.startsWith(str,'aB');//return false;
						plugor.startsWith(str,'aB',true);//return true;
				'
			}
		*/
		startsWith : function(str, prefix,bool){
			if(bool){
				str = str.toLowerCase();
				prefix = prefix.toLowerCase();	
			}
			return str.indexOf(prefix) == 0;
		},
		/*@Annotations
			{parent:'工具篇',name:'endsWith(str,prefix,bool)',title:'',
				describe:'判断字符串是否以XX结尾\n
					调用方法:plugor.endsWith(str, prefix,bool);
					@return boolean
					@param
						str:被判断字符串;
						suffix:判断结尾字符串;
						bool:是否区分大小写,为true则不区分大小写,false则区分大小写;
					@eg
						请参照plugor.startsWith(str, prefix,bool);
				'
			}
		*/
		endsWith : function(str, suffix,bool){
			if(bool){
				str = str.toLowerCase();
				prefix = prefix.toLowerCase();	
			}
			return str.lastIndexOf(suffix) == (str.length - suffix.length);
		},
		/*@Annotations
			{parent:'工具篇',name:'trim(str,prefix,bool)',title:'',
				describe:'去除字符串两端空格\n
					调用方法:plugor.trim(str);
					@return str;
					@param
						str:字符串;
				'
			}
		*/
		trim: function( text ) {
			return (text || "").replace( /^\s+|\s+$/g, "" );
		},
		/*@Annotations
			{parent:'工具篇',name:'color',title:'',
				describe:'颜色转换(不支持color缩写,eg:#ccc要写成#cccccc)\n
					调用方法:
						plugor.color.toRGB(str);
							@return 返回类似 255,0,0 的字符串;
							@param
								str:#ff0000;
						plugor.color.toColor(r, g, b);
							@return 返回类似 #FF0000 的字符串;
							@param
								str:颜色r,g,b;
				'
			}
		*/
		color: {
			hexch : ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'],
			hexStr : '0123456789ABCDEF',
			toHex : function(n) {
				var h, l;
				n = Math.round(n);
				l = n % 16;
				h = Math.floor((n / 16)) % 16;
				return (plugor.color.hexch[h] + plugor.color.hexch[l]);
			},
			toColor: function(r, g, b) {
				return ('#' + plugor.color.toHex(r) + plugor.color.toHex(g) + plugor.color.toHex(b));
			},
			toRGB: function(strhex) {
				r = plugor.color.hexStr.indexOf(strhex.charAt(1).toUpperCase()) * 16	+ plugor.color.hexStr.indexOf(strhex.charAt(2).toUpperCase());
				g = plugor.color.hexStr.indexOf(strhex.charAt(3).toUpperCase()) * 16	+ plugor.color.hexStr.indexOf(strhex.charAt(4).toUpperCase());
				b = plugor.color.hexStr.indexOf(strhex.charAt(5).toUpperCase()) * 16	+ plugor.color.hexStr.indexOf(strhex.charAt(6).toUpperCase());
				return (r + ',' + g + ',' + b)
			}
		},
		/*@Annotations
			{parent:'工具篇',name:'stack(str,prefix,bool)',title:'',
				describe:'栈操作(栈：先入后出)\n
					调用方法:
						plugor.stack();
							@return 一个栈对象
							@eg:
								var st = plugor.stack();
								st.push(100);//压入栈操作
								st.length();//返回栈长度 1
								st.getTop();//获取栈顶元素100
								st.pop();//出栈操作,return 出栈元素
								st.clear();//清除栈
				'
			}
		*/
		stack:function(){
			var stack = function(){
				this._stack = new Array();
			};
			
			stack.prototype={
					
				push : function(x) { // 压入栈操作
					this._stack[this.length()] = x;
				},
				pop : function() { // 出栈操作
					var returnValue = null;
					var stackLength = this.length();
					if (stackLength >= 1) { // 如果不是最后一个元素
						returnValue = this._stack[stackLength - 1]; // 返回该位置的元素值
						this._stack.length = stackLength - 1; // 减少元素的个数
					}
					return returnValue;
				},
			
				getTop : function() { // 获得栈顶元素
					var top = this._stack[this.length() - 1];
					return top==undefined?null:top;
				},
				clear : function() { // 清空栈
					this._stack.length = 0;
				},
				length : function(){
					return this._stack.length;
				}
			};
			return new stack();	
		}
		
	});
	
})();